﻿#include "OiPCH.hpp"

#include <QtCharts/QChart>
#include <QtCharts/QValueAxis>
#include "OiResultWidget.hpp"

namespace Oi
{
    using namespace PLScannerCore;
    static QFont getFont(int size)
    {
        QFont font;
        if (size > 1)
        {
            font.setPixelSize(size);
        }
        return font;
    }
    namespace PLScannerDll
    {
        class PlyPageImpl : public Impl<PlyPage>
        {
        public:
            void init();
            void updateParams();
            void updateLayout(int nMeasurePoint);
            void updateMeasureWidget(MeasureWidget* label, int index, QString key);
            void updateTol(ValueLabel* label, int index, QString key);
            void updateTol(double& upper, double& lower, int index, QString key);
            void setTitalLable(QLabel* pLable, int backColor = 0);
            void updateParamDefault();
            void updateParamTempl();

        public:
            ProductParams _params;
            DefinitionType _tp = DefinitionType::DT_Mutational;

        public:
            ToolProfilesView* _profile;
            QVBoxLayout* _mainLayout = nullptr;
            QWidget* _pFirstWidget;
            QWidget* _pSecondWidget;
//            LineView* _tread;
            ValueLabel* _width;
            ValueLabel* _width1;
            ValueLabel* _thickness1;
            ValueLabel* _thickness2;
            ValueLabel* _thickness3;
            ValueLabel* _thickness4;
            ValueLabel* _thickness5;
            double _widthStd;
            double _widthTol;
            double _thickness1Std;
            double _thickness1Tol;
            double _thickness2Std;
            double _thickness2Tol;
            double _thickness3Std;
            double _thickness3Tol;
            double _thickness4Std;
            double _thickness4Tol;
            double _thickness5Std;
            double _thickness5Tol;

        public:
            QMap<ValueLabel*, double> warningValue;
            QMap<ValueLabel*, double> errorValue;
            QList<MeasureWidget*> _lstWidget;
            double _errorThicknessRange;
            double _errorWidthRange;
            double _edgeThickness;
            int    _precision;
            int    _measureNum;
            QHBoxLayout* _leftLabLayout = nullptr;
            QHBoxLayout* _rightLabLayout = nullptr;
            QMap<QString, ResultWidget*> _resWidMap;
        };

        void PlyPageImpl::init()
        {
            OI_Q(PlyPage);
            _measureNum = Core::OiSettings()->value("View/MeasureNum", 4).toInt();

            _leftLabLayout = new QHBoxLayout();
            //int detectMode = Core::OiSettings()->value("DetectMode", 0).toInt();
            //if (detectMode == 0)
            //{
            //    _rightLabLayout = new QHBoxLayout();
            //
            //    for (int i = 0; i < 2; i++)
            //    {
            //        QHBoxLayout* pLabLayout;
            //        if (i == 0)
            //        {
            //            pLabLayout = _leftLabLayout;
            //        }
            //        else
            //        {
            //            pLabLayout = _rightLabLayout;
            //        }
            //        MeasureWidget* pWidget = new MeasureWidget(q);
            //        pWidget->init(QString(""));
            //        pWidget->_pLabStandard->setText(PlyPage::tr("标准值"));
            //        pWidget->setTitalLable(pWidget->_pLabStandard, 0);
            //        pWidget->_pLabMeasure->setText(PlyPage::tr("测量值"));
            //        pWidget->setTitalLable(pWidget->_pLabMeasure, 0);
            //        pWidget->_pLabDisValue->setText(PlyPage::tr("差异值"));
            //        pWidget->setTitalLable(pWidget->_pLabDisValue, 0);
            //        pLabLayout->addWidget(pWidget->_pLableWidget);
            //
            //        //MeasureWidget* pWidthWidget = new MeasureWidget(q);
            //        //pWidthWidget->init("总宽");
            //        //pLabLayout->addWidget(pWidthWidget->_pLableWidget);
            //
            //        for (int index = 0; index < _measureNum; index++)
            //        {
            //            QString strName = QString("测量点T%1").arg(index + 1 + i * _measureNum);
            //            MeasureWidget* cWidget = new MeasureWidget(q);
            //            cWidget->init(strName);
            //            _lstWidget.append(cWidget);
            //
            //            pLabLayout->addWidget(cWidget->_pLableWidget);
            //        }
            //    }
            //}

            QVBoxLayout* mainLayout = new QVBoxLayout(q);

            _profile = new ToolProfilesView();

            _profile->setPageFlag(PMP_ThicknessMeasure);


            _profile->setParams(_params);

            mainLayout->addWidget(_profile, 3);
            //if (detectMode == 0)
            //{
            //    mainLayout->addLayout(_leftLabLayout, 1);
            //    mainLayout->addLayout(_rightLabLayout, 1);
            //}
            //else
            {
                QWidget* tempWid = new QWidget(q);
                tempWid->setLayout(_leftLabLayout);
                mainLayout->addWidget(tempWid);
            }

            _profile->winId();

            QMetaObject::invokeMethod(q, "onReady");
        }

        void PlyPageImpl::setTitalLable(QLabel* pLable,int backColor)
        {
            pLable->setFont(getFont(38));
            pLable->setFixedSize(200, 42);
            pLable->setAlignment(Qt::AlignCenter);
            if (backColor == 0)
            {
                pLable->setStyleSheet("QLabel{color: black;border-style: groove;border-radius:5px;}");
            }
            else if (backColor == 1)
            {
                pLable->setStyleSheet("QLabel{color: black;background-color: white;border-style: groove;border-radius:5px;}");
            }
            else if(backColor == 2)
            {
                pLable->setStyleSheet("QLabel{color: black;background-color: green;border-style: groove;border-radius:5px;}");
            }
            else if (backColor == 3)
            {
                pLable->setStyleSheet("QLabel{color: black;background-color: rgb(102, 204, 240);border-style: groove;border-radius:5px;}");
            }
            pLable->setFrameShape(QFrame::Box);
            pLable->setFrameShadow(QFrame::Raised);
        }

        void PlyPageImpl::updateParamDefault()
        {
            OI_Q(PlyPage);

            _profile->setParams(_params);

            if (_lstWidget.isEmpty())
            {
                return;
            }

            for (int i = 0; i < _lstWidget.size(); i++)
            {
                _lstWidget[i]->setValue(0, 1);
                _lstWidget[i]->setValue(0, 2);
            }
            updateMeasureWidget(_lstWidget[0], TT_LeftSide, "y");
            updateMeasureWidget(_lstWidget[0 + _lstWidget.size() / 2], TT_LeftSide, "y");
            int count = min(_params.measureThickness.size(), _lstWidget.size() / 2);
            for (int index = 1; index < count - 1; index++)
            {
                if (index < _lstWidget.size() / 2)
                {
                    updateMeasureWidget(_lstWidget[index], index - 1, "y");
                    updateMeasureWidget(_lstWidget[index + _lstWidget.size() / 2], index - 1, "y");
                }
            }
            if (count > 0)
            {
                updateMeasureWidget(_lstWidget[count - 1], TT_RightSide, "y");
                updateMeasureWidget(_lstWidget[count - 1 + _lstWidget.size() / 2], TT_RightSide, "y");
            }
            else
            {
                updateMeasureWidget(_lstWidget[0], TT_RightSide, "y");
                updateMeasureWidget(_lstWidget[_lstWidget.size() / 2], TT_RightSide, "y");
            }
            OiProfile pfs;
            pfs.push_back(QPointF(-_params.materialsWidth / 2, 0));
            pfs.push_back(QPointF(-_params.materialsWidth / 4, +0.1));
            pfs.push_back(QPointF(+_params.materialsWidth / 4, -0.1));
            pfs.push_back(QPointF(+_params.materialsWidth / 2, 0));
            _params.getMeasureErrorTol(TT_TotolWidth, "x", _errorWidthRange);
            _params.getMeasureErrorTol(TT_MeasureThicknessTool, "y", _errorThicknessRange);
        }

        void PlyPageImpl::updateParamTempl()
        {
            OI_Q(PlyPage);

            _profile->setParams(_params);

            if (_resWidMap.isEmpty())
            {
                ResultWidget* resWid = new ResultWidget("总高(mm)", q);
                _leftLabLayout->addWidget(resWid);
                _resWidMap.insert(resWid->title(), resWid);

                resWid = new ResultWidget("腰高(mm)", q);
                _leftLabLayout->addWidget(resWid);
                _resWidMap.insert(resWid->title(), resWid);

                resWid = new ResultWidget("端点宽(mm)", q);
                _leftLabLayout->addWidget(resWid);
                _resWidMap.insert(resWid->title(), resWid);

                resWid = new ResultWidget("总宽(mm)", q);
                _leftLabLayout->addWidget(resWid);
                _resWidMap.insert(resWid->title(), resWid);
                resWid->hide();

                resWid = new ResultWidget("半高宽(mm)", q);
                _leftLabLayout->addWidget(resWid);
                _resWidMap.insert(resWid->title(), resWid);
                resWid->hide();

                resWid = new ResultWidget("腰宽(mm)", q);
                _leftLabLayout->addWidget(resWid);
                _resWidMap.insert(resWid->title(), resWid);
                
                resWid = new ResultWidget("底部宽(mm)", q);
                _leftLabLayout->addWidget(resWid);
                _resWidMap.insert(resWid->title(), resWid);
                
                resWid = new ResultWidget("截面积(mm²)", q);
                _leftLabLayout->addWidget(resWid);
                _resWidMap.insert(resWid->title(), resWid);

                QSpacerItem* si = new QSpacerItem(100, 20);
                _leftLabLayout->addItem(si);
            }
        }

        void PlyPageImpl::updateParams()
        {
            OI_Q(PlyPage);

            if (q->isTempl())
            {
                updateParamTempl();
            }
            else
            {
                updateParamDefault();
            }
        }

        void PlyPageImpl::updateMeasureWidget(MeasureWidget* label, int index, QString key)
        {
            if (!label || label == nullptr)
            {
                return;
            }
            label->setEnabled(true);
            int enable = 0;
            double warningTol = 0.0;
            double errorTol = 0.0;
            double stdValue = 0.0;
            label->_difValue = 0;
            label->_errorValue = 0;
            label->_maxErrorValue = 0;
            label->_maxWarningValue = 0;
            label->_minErrorValue = 0;
            label->_measureValue = 0;
            label->_minWarningValue = 0;
            label->_standardValue = 0;
            label->_warningValue = 0;
            label->setValue(stdValue, 1);
            int defineVal = index + TT_MeasureThicknessTool;
            if (index == TT_LeftSide || index == TT_RightSide)
            {
                defineVal = index;
            }
            if (_params.getMeasureWarningTol(index, "y", warningTol) &&
                _params.getMeasureErrorTol(index, "y", errorTol) &&
                _params.getStdValue(defineVal, "y", stdValue))
            {
                if (TC_WarningEnable)
                {
                    label->setEarlyUpper(stdValue + warningTol);
                    label->setEarlyLower(stdValue - warningTol);
                    //                        warningValue[label] = warningTol;
                }

                if (TC_ErrorEnable)
                {
                    label->setUpper(stdValue + errorTol);
                    label->setLower(stdValue - errorTol);
                }
                QString strValue = QString::number(stdValue, 'f', 2);
                double val = strValue.toDouble();
                label->setValue(val, 1);
            }
            else
            {
                label->setEnabled(false);
            }
        }

        void PlyPageImpl::updateLayout(int nMeasurePoint)
        {
            OI_Q(PlyPage);
            for (int i = 0; i < _lstWidget.size()/2;i++)
            {
                if (i > nMeasurePoint)
                {
                    _lstWidget[i]->setVisible(false);
                    _lstWidget[i+ _lstWidget.size() / 2]->setVisible(false);
                }
                else
                {
                    _lstWidget[i]->setVisible(true);
                    _lstWidget[i + _lstWidget.size() / 2]->setVisible(true);
                }
            }
        }

        void PlyPageImpl::updateTol(ValueLabel* label, int index, QString key)
        {
            int enable = 0;
            double warningTol = 0.0;
            double errorTol = 0.0;
            double stdValue = 0.0;

            if (_params.getMeasureEnable(index, key, enable) &&
                _params.getMeasureWarningTol(index, key, warningTol) &&
                _params.getMeasureErrorTol(index, key, errorTol) &&
                _params.getStdValue(index, key, stdValue))
            {
                label->setEnabled(true);
                if (enable & TC_WarningEnable)
                {
                    label->setEarlyUpper(stdValue + warningTol);
                    label->setEarlyLower(stdValue - warningTol);
                    warningValue[label] = warningTol;
                }

                if (enable & TC_ErrorEnable)
                {
                    label->setUpper(stdValue + errorTol);
                    label->setLower(stdValue - errorTol);
                    errorValue[label] = errorTol;
                }
                label->setStdValue(stdValue);
            }
            else
            {
                label->setEnabled(false);
            }
        }

        void PlyPageImpl::updateTol(double& std, double& err, int index, QString key)
        {
            double errorTol = 0.0;
            double stdValue = 0.0;

            if (_params.getMeasureErrorTol(index, key, errorTol) &&
                _params.getStdValue(index, key, stdValue))
            {
                err = errorTol;
                std = stdValue;
            }
            else
            {
                std = 0;
                err = 0;
            }
        }

        PlyPage::PlyPage(QWidget * parent /*= nullptr*/)
            : PageAbstract(parent)
        {
            OI_I(PlyPage)->init();
        }

        void PlyPage::setParams(const ProductParams& params)
        {
            OI_F(PlyPage);
            ProductParams tmpParams = params;

            d->_params = tmpParams;
            auto& dpArr = d->_params.definitionPoints;
            if (!dpArr.isEmpty())
            {
                d->_tp = static_cast<DefinitionType>(dpArr.first().type);
            }
            else
            {
                d->_tp = DT_TempleStandLine;
            }
            d->updateParams();
        }

        int PlyPage::setResult(const PLScannerCore::WorkResult::Result& result)
        {
            OI_F(PlyPage);
            d->_profile->setResult(result);
            return WorkResult::RC_Success;
        }

        int PlyPage::setMsrResult(const std::vector<QPointF>& msrRes, bool insert)
        {
            OI_F(PlyPage);
            d->_profile->setMsrResult(msrRes);
            auto res = d->_profile->msrResult();
            auto& msrArr = res.first;
            auto& templArr = res.second;
            if (msrArr.size() < 9 || templArr.size() < 9)
            {
                return WorkResult::RC_Success;
            }
            d->_resWidMap["端点宽(mm)"]->setValue(msrArr[1], templArr[1]);
            d->_resWidMap["腰宽(mm)"]->setValue(msrArr[2], templArr[2]);
            d->_resWidMap["总宽(mm)"]->setValue(msrArr[3], templArr[3]);
            d->_resWidMap["腰高(mm)"]->setValue(msrArr[4], templArr[4]);
            d->_resWidMap["总高(mm)"]->setValue(msrArr[5], templArr[5]);
            d->_resWidMap["半高宽(mm)"]->setValue(msrArr[6], templArr[6]);
            d->_resWidMap["底部宽(mm)"]->setValue(msrArr[7], templArr[7]);
            d->_resWidMap["截面积(mm²)"]->setValue(msrArr[8], templArr[8]);

            if (insert)
            {
                DataRow row;
                row.datetime = QDateTime::currentDateTime();
                row.formula = d->_params.specName;
                row.user = UserManage::instance()->current();

                row.result = msrArr[0];
                row.endPointWidth = msrArr[1];
                row.waistWidth = msrArr[2];
                row.waistHeight = msrArr[4];
                row.fullHeight = msrArr[5];
                row.bottomWidth = msrArr[7];
                row.area = msrArr[8];

                Database::instance()->insert(row);
            }

            return msrArr[0];
        }

        std::pair<std::vector<double>, std::vector<double>> PlyPage::msrResult()
        {
            return OI_IMPL()->_profile->msrResult();
        }

        void PlyPage::setRateCPCPK(const std::vector<Math::Point3f>& rateCPCPK)
        {
            OI_F(PlyPage);

            if (rateCPCPK.size() < 6)
            {
                return;
            }

            d->_resWidMap["端点宽(mm)"]->setRateCPCPK(rateCPCPK[0].x(), rateCPCPK[0].y(), rateCPCPK[0].z());
            d->_resWidMap["腰宽(mm)"]->setRateCPCPK(rateCPCPK[1].x(), rateCPCPK[1].y(), rateCPCPK[1].z());
            d->_resWidMap["腰高(mm)"]->setRateCPCPK(rateCPCPK[2].x(), rateCPCPK[2].y(), rateCPCPK[2].z());
            d->_resWidMap["总高(mm)"]->setRateCPCPK(rateCPCPK[3].x(), rateCPCPK[3].y(), rateCPCPK[3].z());
            d->_resWidMap["底部宽(mm)"]->setRateCPCPK(rateCPCPK[4].x(), rateCPCPK[4].y(), rateCPCPK[4].z());
            d->_resWidMap["截面积(mm²)"]->setRateCPCPK(rateCPCPK[5].x(), rateCPCPK[5].y(), rateCPCPK[5].z());
        }

        void PlyPage::onReady()
        {
            OI_F(PlyPage);
            d->_profile->zoomFit();
            //d->_tread->zoomFit();
        }

        bool PlyPage::isTempl()
        {
            OI_F(PlyPage);
            return d->_tp >= DT_TempleStandLine && d->_tp <= DT_TempleStandArcsMark;
        }

        void PlyPage::resizeEvent(QResizeEvent *event)
        {
            OI_F(PlyPage);
            d->_profile->zoomFit();
            //d->_tread->zoomFit();
        }

        void PlyPage::setRun(bool flag)
        {
            OI_F(PlyPage);
        }

        void PlyPage::toCurrent()
        {
            OI_F(PlyPage);
        }

        MeasureWidget::MeasureWidget(QWidget* parent)
        {
            _pLableWidget = new QWidget(parent);
        }

        MeasureWidget::~MeasureWidget()
        {

        }

        QWidget* MeasureWidget::init(QString name)
        {

            _FontSize = Core::OiSettings()->value("View/WidgetFontSize").toInt();
            _Width = Core::OiSettings()->value("View/FixedWidth").toInt();
            _Hight = Core::OiSettings()->value("View/FixedHight").toInt();


            _pLabTitle = new QLabel();
            _pLabStandard = new QLabel();
            _pLabMeasure = new QLabel();
            _pLabDisValue = new QLabel();
            QVBoxLayout* pLay = new QVBoxLayout(_pLableWidget);
            setTitalLable(_pLabTitle, 0);
            setTitalLable(_pLabStandard, 1);
            setTitalLable(_pLabMeasure, 2);
            setTitalLable(_pLabDisValue, 3);
            pLay->addWidget(_pLabTitle);
            pLay->addWidget(_pLabStandard);
            pLay->addWidget(_pLabMeasure);
            pLay->addWidget(_pLabDisValue);

            _pLabTitle->setText(name);
            //_pLabStandard->setText(name);
            //_pLabMeasure->setText(name);
            //_pLabDisValue->setText(name);
            return _pLableWidget;
        }

        void MeasureWidget::setTitalLable(QLabel* pLable, int backColor)
        {
            pLable->setFont(getFont(_FontSize));
            pLable->setFixedSize(_Width, _Hight);
            pLable->setAlignment(Qt::AlignCenter);
            if (backColor == 0)
            {
                pLable->setStyleSheet("QLabel{color: black;border-style: groove;border-radius:5px;}");
            }
            else if (backColor == 1)
            {
                pLable->setStyleSheet("QLabel{color: black;background-color: white;border-style: groove;border-radius:5px;}");
            }
            else if (backColor == 2)
            {
                pLable->setStyleSheet("QLabel{color: black;background-color: green;border-style: groove;border-radius:5px;}");
            }
            else if (backColor == 3)
            {
                pLable->setStyleSheet("QLabel{color: black;background-color: rgb(102, 204, 240);border-style: groove;border-radius:5px;}");
            }
            pLable->setFrameShape(QFrame::Box);
            pLable->setFrameShadow(QFrame::Raised);
        }

        int MeasureWidget::setValue(double value, int type)
        {
            QString strValue = QString::number(value);
            if (value == 0)
            {
                strValue = "";
            }
            switch (type)
            {
            case 1:
                _pLabStandard->setText(strValue);
                _standardValue = value;
                break;
            case 2:
                _measureValue = value;
                _pLabMeasure->setText(strValue);
                _difValue = value - _standardValue;
                strValue = QString::number(_difValue);
                if (_difValue == 0)
                {
                    strValue = "";
                }
                _pLabDisValue->setText(strValue);
                if (value >= _maxErrorValue || value <= _minErrorValue)
                {
                    _pLabMeasure->setStyleSheet("QLabel{color: black;background-color: rgb(238, 60, 60)}");
                    _pLabDisValue->setStyleSheet("QLabel{color: red;background-color: rgb(102, 204, 240)}");
                    return 300;
                }
                else if (value >= _maxWarningValue || value <= _minWarningValue)
                {
                    _pLabMeasure->setStyleSheet("QLabel{color: black;background-color: green;}");
                    _pLabDisValue->setStyleSheet("QLabel{color: black;background-color: rgb(102, 204, 240)}");
                    return 200;
                }
                else
                {
                    _pLabMeasure->setStyleSheet("QLabel{color: black;background-color: green;border-style: groove;border-radius:5px;}");
                    return 1;
                }
                break;
            default:
                break;
            }
            return 1;
        }

        void MeasureWidget::setEarlyUpper(double value)
        {
            _maxWarningValue = value;
            _warningValue = _maxWarningValue - _standardValue;
        }

        void MeasureWidget::setEarlyLower(double value)
        {
            _minWarningValue = value;
            _warningValue = _standardValue - _maxWarningValue;
        }

        void MeasureWidget::setUpper(double value)
        {
            _maxErrorValue = value;
            _errorValue = _maxErrorValue - _standardValue;

        }

        void MeasureWidget::setLower(double value)
        {
            _minErrorValue = value;
            _errorValue = _standardValue - _maxErrorValue;
        }
    }
}